/*
 * 文件操作模板库 - 专注于文件读写和数据持久化
 * 使用场景: 需要从文件读取数据或将结果写入文件的题目
 * 包含: 基础文件IO、CSV处理、图数据读取、二进制操作、内存映射文件
 * 特点: 简化文件操作，提供常用数据格式的快速读写
 */

#pragma once
#include "basic_template.hpp"
#include <fstream>
#include <sstream>

// 文件操作工具类 - 提供常用的文件读写功能
// 使用场景: 处理文件输入输出、数据持久化、批量数据处理
// 特点: 封装了常用的文件操作，简化代码编写
class FileOperations
{
public:
    // 读取整个文件内容
    static string read_file(const string &filename)
    {
        ifstream file(filename);
        if (!file.is_open()) {
            throw runtime_error("无法打开文件: " + filename);
        }

        stringstream buffer;
        buffer << file.rdbuf();
        return buffer.str();
    }

    // 按行读取文件
    static vector<string> read_lines(const string &filename)
    {
        ifstream file(filename);
        if (!file.is_open()) {
            throw runtime_error("无法打开文件: " + filename);
        }

        vector<string> lines;
        string line;
        while (getline(file, line)) {
            lines.push_back(line);
        }
        return lines;
    }

    // 写入文件
    static void write_file(const string &filename, const string &content)
    {
        ofstream file(filename);
        if (!file.is_open()) {
            throw runtime_error("无法创建文件: " + filename);
        }
        file << content;
    }

    // 写入多行到文件
    static void write_lines(const string &filename, const vector<string> &lines)
    {
        ofstream file(filename);
        if (!file.is_open()) {
            throw runtime_error("无法创建文件: " + filename);
        }

        for (size_t i = 0; i < lines.size(); ++i) {
            if (i > 0)
                file << "\n";
            file << lines[i];
        }
    }

    // 追加内容到文件
    static void append_file(const string &filename, const string &content)
    {
        ofstream file(filename, ios::app);
        if (!file.is_open()) {
            throw runtime_error("无法打开文件: " + filename);
        }
        file << content;
    }

    // 检查文件是否存在
    static bool file_exists(const string &filename)
    {
        ifstream file(filename);
        return file.good();
    }

    // 读取CSV文件
    static vector<vector<string>> read_csv(const string &filename, char delimiter = ',')
    {
        vector<vector<string>> data;
        ifstream file(filename);

        if (!file.is_open()) {
            throw runtime_error("无法打开CSV文件: " + filename);
        }

        string line;
        while (getline(file, line)) {
            vector<string> row;
            stringstream ss(line);
            string cell;

            while (getline(ss, cell, delimiter)) {
                row.push_back(cell);
            }
            data.push_back(row);
        }

        return data;
    }

    // 写入CSV文件
    static void write_csv(const string &filename, const vector<vector<string>> &data, char delimiter = ',')
    {
        ofstream file(filename);
        if (!file.is_open()) {
            throw runtime_error("无法创建CSV文件: " + filename);
        }

        for (size_t i = 0; i < data.size(); ++i) {
            for (size_t j = 0; j < data[i].size(); ++j) {
                if (j > 0)
                    file << delimiter;
                file << data[i][j];
            }
            if (i < data.size() - 1)
                file << "\n";
        }
    }
};

// 便捷的文件读写函数
namespace FileIO
{
// 快速读取整数数组
vector<int> read_int_array(const string &filename)
{
    vector<int> result;
    ifstream file(filename);
    int x;
    while (file >> x) {
        result.push_back(x);
    }
    return result;
}

// 快速读取矩阵
vector<vector<int>> read_matrix(const string &filename)
{
    vector<vector<int>> matrix;
    ifstream file(filename);
    string line;

    while (getline(file, line)) {
        vector<int> row;
        stringstream ss(line);
        int x;
        while (ss >> x) {
            row.push_back(x);
        }
        if (!row.empty()) {
            matrix.push_back(row);
        }
    }

    return matrix;
}

// 快速写入数组
void write_array(const string &filename, const vector<int> &arr, const string &separator = " ")
{
    ofstream file(filename);
    for (size_t i = 0; i < arr.size(); ++i) {
        if (i > 0)
            file << separator;
        file << arr[i];
    }
}

// 快速写入矩阵
void write_matrix(const string &filename, const vector<vector<int>> &matrix, const string &separator = " ")
{
    ofstream file(filename);
    for (size_t i = 0; i < matrix.size(); ++i) {
        for (size_t j = 0; j < matrix[i].size(); ++j) {
            if (j > 0)
                file << separator;
            file << matrix[i][j];
        }
        if (i < matrix.size() - 1)
            file << "\n";
    }
}

// 从文件读取图的邻接表
vector<vector<int>> read_graph(const string &filename, int &n, int &m)
{
    ifstream file(filename);
    file >> n >> m;

    vector<vector<int>> adj(n);
    for (int i = 0; i < m; ++i) {
        int u, v;
        file >> u >> v;
        u--;
        v--; // 转换为0-based索引
        adj[u].push_back(v);
        adj[v].push_back(u); // 无向图
    }

    return adj;
}

// 从文件读取加权图
vector<vector<pair<int, int>>> read_weighted_graph(const string &filename, int &n, int &m)
{
    ifstream file(filename);
    file >> n >> m;

    vector<vector<pair<int, int>>> adj(n);
    for (int i = 0; i < m; ++i) {
        int u, v, w;
        file >> u >> v >> w;
        u--;
        v--; // 转换为0-based索引
        adj[u].push_back({v, w});
        adj[v].push_back({u, w}); // 无向图
    }

    return adj;
}

// 从文件读取树
vector<vector<int>> read_tree(const string &filename, int &n)
{
    ifstream file(filename);
    file >> n;

    vector<vector<int>> adj(n);
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        file >> u >> v;
        u--;
        v--; // 转换为0-based索引
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    return adj;
}
} // namespace FileIO

// 二进制文件操作
namespace BinaryIO
{
// 写入二进制数据
template <typename T>
void write_binary(const string &filename, const vector<T> &data)
{
    ofstream file(filename, ios::binary);
    if (!file.is_open()) {
        throw runtime_error("无法创建二进制文件: " + filename);
    }

    size_t size = data.size();
    file.write(reinterpret_cast<const char *>(&size), sizeof(size));
    file.write(reinterpret_cast<const char *>(data.data()), size * sizeof(T));
}

// 读取二进制数据
template <typename T>
vector<T> read_binary(const string &filename)
{
    ifstream file(filename, ios::binary);
    if (!file.is_open()) {
        throw runtime_error("无法打开二进制文件: " + filename);
    }

    size_t size;
    file.read(reinterpret_cast<char *>(&size), sizeof(size));

    vector<T> data(size);
    file.read(reinterpret_cast<char *>(data.data()), size * sizeof(T));

    return data;
}
} // namespace BinaryIO

// 内存映射文件操作 (适用于大文件)
class MemoryMappedFile
{
private:
    string filename;
    size_t file_size;

public:
    MemoryMappedFile(const string &fname) : filename(fname)
    {
        // 简化版本，实际使用时可能需要平台特定的实现
        ifstream file(filename, ios::ate | ios::binary);
        if (file.is_open()) {
            file_size = file.tellg();
        } else {
            file_size = 0;
        }
    }

    size_t size() const { return file_size; }

    // 读取指定范围的数据
    string read_range(size_t start, size_t length)
    {
        ifstream file(filename, ios::binary);
        file.seekg(start);

        string buffer(length, '\0');
        file.read(&buffer[0], length);

        return buffer;
    }
};
